<template>
    <el-table class="uiot-table" :class="{'has-rowcheckbox':showRowCheckbox}" ref="table" v-loading="loading" :row-key="rowKey" :border="border" :default-sort="defaultSort" :highlight-current-row="highlightCurrentRow" :data="tableRows" :header-row-style="customHeadRowStyle"
        :header-cell-style="customHeadCellStyle" :cell-style="customCellStyle" :row-style="customRowStyle" :height="height" :max-height="maxHeight" :cell-class-name="customCellClassName" :row-class-name="customRowClassName" :current-row-key.sync="currentRowKey" v-bind="$attrs" v-on="$listeners"
        @sort-change="handleSortChange" @header-click="handleHeaderClick" @row-click="handleRowClick" @row-dblclick="handleRowDBlClick" @current-change="handleCurrentRowChange" @select="handleRowCheck" @selection-change="handleSelectionChange">
        <template v-if="$slots.default||(columns&&columns.length>0)">
            <el-table-column v-if="showRowCheckbox" type="selection" width="50px" align="center">
            </el-table-column>
            <el-table-column v-if="showLinenum" type="index" label="No." header-align="center" align="center" :width="$idxNoWidth" :index="getRowIndex">
            </el-table-column>
        </template>
        <!-- 如果有slot则渲染slot -->
        <template v-if="!$slots.default&&columns">
            <el-table-column v-for="(col,index) of columns" :key="index" v-bind="col" />
        </template>
        <slot v-else></slot>
    </el-table>
</template>

<script>
// import { exportTo } from '@/utils/exportTo'

function parseOrder(order) {
    return typeof order === 'boolean' ? (order ? 'ascending' : 'descending') : order
}

const computed = {
    /** @returns {Vue} */
    table() {
        return this.$refs.table
    },
    border() {
        return this.tableStyle == 'normal'
    },
    /** @this {number} */
    outsideHeight() {
        return this.$el.clientHeight
    },
    clearSelection() {
        return this.table?.clearSelection
    },
    toggleRowSelection() {
        return this.table?.toggleRowSelection
    },
    toggleAllSelection() {
        return this.table?.toggleAllSelection
    },
    toggleRowExpansion() {
        return this.table?.toggleRowExpansion
    },
    clearSort() {
        return this.table?.clearSort
    },
    clearFilter() {
        return this.table?.clearFilter
    },
    doLayout() {
        return this.table?.doLayout
    },
    store() {
        return this.table?.store
    },
    // el-table内部的currentRow
    _currentRow() {
        return this.store?.states.currentRow
    },
    /** @returns {any[]} */
    _rowSelection() {
        return this.store?.states.selection
    },
}

export default {
    inheritAttrs: false,
    name: 'UiotTable',
    props: {
        /** 是否显示loading */
        loading: {
            type: Boolean,
            default: false,
        },
        /** 自定义列，优先级小于slot.default */
        columns: Array,
        /** 数据源 */
        tableRows: {
            type: Array,
            default: () => []
        },
        /** 表格排序参数 */
        tableSort: Object,
        /** 行数据主键属性 */
        rowKey: {
            type: String,
            default: 'id'
        },
        /** 当前页码 */
        pageIndex: Number,
        /** 页大小 */
        pageSize: Number,
        /** 当前选中行，支持双向绑定*/
        currentRow: Object,
        /** 是否可以反选当前行，即点击当前行时取消选中状态 */
        reverseCurrentRow: Boolean,
        /** 是否显示行号 */
        showLinenum: {
            type: Boolean,
            default: true,
        },
        /** 是否在每行前面显示复选框 */
        showRowCheckbox: {
            type: Boolean,
            default: false,
        },
        /** 表格风格,用于控制样式 */
        tableStyle: {
            type: String,
            validator: value => ['normal', 'concise'].indexOf(value) > -1
        },
        /** 原生属性 */
        size: {
            type: String,
            default: 'mini',
        },
        /** 原生属性 */
        height: {
            type: [String, Number],
            default: '100%',
        },
        /** 原生属性 */
        maxHeight: {
            type: [String, Number],
            default: '100%',
        },
        /** 原生属性，高亮当前行 */
        highlightCurrentRow: {
            type: Boolean,
            default: false,
        },
        /** 原生属性[只写]  -> ps: 设置此属性只会在外观上改变当前行 */
        currentRowKey: [String, Number],
        /** 当前勾选行集合，支持双向绑定 */
        rowSelection: Array,
        /** 原生属性 */
        cellStyle: Function,
        /** 原生属性 */
        rowStyle: Function,
        /** 原生属性 */
        rowClassName: Function,
        /** 原生属性 */
        cellClassName: Function,
    },
    created() {
        // debounce请自己实现
        this.rowClickDeb = this.$utils.debounce((row, column, event) => {
            this.$emit('_row-click', row, column, event)
        }, 300)
    },
    mounted() {
        if (this.tableSort) {
            this.setDefaultSort(this.tableSort.field || '', this.tableSort.order)
        }
        console.log('uiot-table -> mounted', this.table, this.store)
    },
    data() {
        return {
            rowClickDeb: null,
            defaultSort: {
                prop: '',
                order: 'ascending',
            },
            lastTableRows: null,
            cacheData: {
                // 此变量的作用是在handleRowClick事件后才更新当前行，目前仅供reverseCurrentRow功能使用
                // 因为el-table在rowclick事件触发时，内部先处理了当前行，然后再抛出此事件，这样的话参数中的row永远都是当前行
                currentRow: null,
                lastRow: null,
                pageIndex: 1,
                pageSize: 1
            },
            selectedRows: [],
            selectedRange: [-1, -1],
        }
    },
    computed: computed,
    watch: {
        'tableSort.default'(nval) {
            // 备份当前sort
            const { field, order } = this.tableSort
            // 获取到默认sort
            this.tableSort.default()
            // 设置默认sort
            this.setDefaultSort(this.tableSort.field, this.tableSort.order)
            // 还原sort
            this.tableSort.field = field
            this.tableSort.field = order
        },
        showLinenum(val) {
            if (val) {
                if (typeof this.pageIndex != 'number') throw '如果显示行号，必须传入"pageIndex"属性'
                if (typeof this.pageSize != 'number') throw '如果显示行号，必须传入"pageSize"属性'
            }
        },
        tableRows(nval, oval) {
            // 如果有当前行，则清除
            if (this.cacheData.currentRow) {
                this.setCurrentRow()
            }
            this.$nextTick(() => {
                if (this.doLayout) this.doLayout()

                // 只有数据源改变了才去更新页码和页大小，否则还在loading状态，行号就已经变了，视觉效果不好
                this.cacheData.pageIndex = this.pageIndex || 1
                this.cacheData.pageSize = this.pageSize || 1
            })
        },
        currentRow(nval, oval) {
            if (nval != this.cacheData.currentRow) {
                // 这里一定要nextTick，因为在watch表格数据源变化时，会清除当前行
                this.$nextTick(() => this.setCurrentRow(nval))
            }
        }
    },
    methods: {
        // #region 方法
        scrollTo() {
            this.table?.$refs.bodyWrapper?.scrollTo(...arguments)
        },
        sort(prop, order) {
            return this.table?.sort(prop, parseOrder(order))
        },
        setDefaultSort(prop, order) {
            this.defaultSort.prop = prop ?? ''
            this.defaultSort.order = parseOrder(order)
        },
        /**
         * 重写setCurrentRow方法，请勿调用el-table提供的setCurrentRow
         */
        setCurrentRow(row = null) {
            if (this.cacheData.currentRow != row) {

                this.cacheData.lastRow = this.cacheData.currentRow
                this.cacheData.currentRow = row

                if (this.currentRow != this.cacheData.currentRow) {
                    this.$emit('update:currentRow', this.cacheData.currentRow)
                }
                this.$emit('_current-change', this.cacheData.currentRow, this.cacheData.lastRow)

                console.log('表格当前行改变 -> ', 'currentRow', this.cacheData.currentRow, 'lastRow', this.cacheData.lastRow)
            }

            if (this._currentRow != row) {
                // 如果el-table内部的当前行不是传入的row，则更新一下
                this.table.setCurrentRow(row)
            }
        },
        // #endregion

        // #region 事件处理
        handleRowCheck(selection, row) {
            if (this.showRowCheckbox && this.selectedRows.length > 0 && this.selectedRows.includes(row)) {
                const check = selection.includes(row)
                for (const row of this.selectedRows) {
                    this.toggleRowSelection(row, check)
                }
            }
        },
        /**
         * @param {MouseEvent} event
         */
        handleRowClick(row, column, event) {
            event.preventDefault()

            console.log('row-click -> ', row, column, event)
            this.rowClickDeb(row, column, event)

            if (this.showRowCheckbox) {
                if (!this.tableRows && this.selectedRows.length > 0) {
                    this.selectedRows = []
                    return
                }

                if (event.shiftKey && this.cacheData.currentRow) {
                    // 找出上一次点击行与当前点击行的序号
                    this.selectedRows = []
                    window.getSelection().removeAllRanges()
                    let startNo = this.tableRows.findIndex((item) =>
                        this.cacheData.currentRow && item === this.cacheData.currentRow
                    )
                    let endNo = this.tableRows.findIndex((item) => item === row)

                    if (startNo != -1 && endNo != -1) {
                        // 正序一下
                        if (startNo > endNo) {
                            let temp = endNo
                            endNo = startNo
                            startNo = temp
                        }
                        for (let i = startNo; i <= endNo; i++) {
                            this.selectedRows.push(this.tableRows[i])
                        }
                        console.log('多选', startNo, endNo, this.selectedRows)
                        // 多选不需要设置当前行
                        return
                    }
                }
                else if (event.ctrlKey) {
                    if (this.selectedRows.includes(row)) {
                        this.selectedRows.$remove(row)
                    }
                    else {
                        this.selectedRows.push(row)
                    }
                    this.table.setCurrentRow()
                    return
                    // if()
                    // this.toggleRowSelection(row)
                }
            }

            if (this.selectedRows.length > 0) this.selectedRows = []
            if (this.reverseCurrentRow && row === this.cacheData.currentRow) {
                this.setCurrentRow()
            }
            else {
                this.setCurrentRow(row)
            }

        },
        handleRowDBlClick() {
            this.rowClickDeb.cancel()
            console.log('row-dblclick -> ')
        },
        handleHeaderClick() {
        },
        handleCurrentRowChange(newRow, oldRow) {
            // this.cacheData.lastRow = oldRow
            // if (this.currentRow != newRow) {
            //   this.$emit('update:currentRow', newRow)
            // }
            // console.log('表格当前行改变 -> ', newRow, oldRow)
        },
        handleSortChange({ column, prop, order }) {
            console.log(column, prop, order)
            if (typeof this.tableSort == 'object') {
                if (order) {
                    this.tableSort.field = prop
                    this.tableSort.order = order === 'descending' ? false : true
                }
                else if (typeof this.tableSort.default == 'function') {
                    this.tableSort.default()
                }
                else {
                    this.tableSort.field = this.defaultSort.prop
                    this.tableSort.order = this.defaultSort.order === 'descending' ? false : true
                }
            }
            // this.$emit('sort-change', ...arguments)
        },
        handleSelectionChange(val) {
            if (typeof this.rowSelection != 'object') throw '如果开启了"showRowCheckbox", 必须传入"rowSelection"'
            this.$emit('update:rowSelection', val)
        },
        // #endregion

        getRowIndex(index) {
            return index + 1 + (this.cacheData.pageIndex - 1) * this.cacheData.pageSize //this.loading ? index + 1 + (this.lastPageIndex - 1) * this.lastPageSize : index + 1 + (this.pageIndex - 1) * this.pageSize
        },
        /**
         * 获取table的列头文本（获取到的是i18n翻译后的）
         */
        getColumnLabelMap() {
            const columnLabelMap = {}
            for (const col of this.table.columns) {
                if ((!this.showLinenum && col.type == 'index') || col.type === 'selection') continue
                if (col.property && col.label) {
                    columnLabelMap[col.property] = col.label
                }
            }
            return columnLabelMap
        },
        exportTo({ showLinenum = false, columnMap, name }) {
            if (this.tableRows && this.tableRows.length > 0 && this.table.columns.length > 0) {

                columnMap = columnMap ? columnMap : this.getColumnLabelMap()

                // 替换列标题
                const data = this.tableRows.map((row) => {
                    const temp = {}
                    for (const key in columnMap) {
                        // label : value
                        temp[columnMap[key]] = row[key]
                    }
                    return temp
                })
                // exportTo({
                //     data: data,
                //     dataType: 'json',
                //     fileName: name
                // })
            }
        },

        // #region 样式、类重载
        customCellClassName({ row, column, rowIndex, columnIndex }) {
            let clsname = ''
            if (this.cellClassName) clsname += this.cellClassName(arguments[0]) || ''
            return clsname.trim()

        },
        customRowClassName({ row, rowIndex }) {
            let clsname = ''
            if (this.showRowCheckbox) {
                // if (this._rowSelection && this._rowSelection.indexOf(row) != -1) {
                //   clsname += ' is-checked'
                // }
                // if (rowIndex >= this.selectedRange[0] && rowIndex <= this.selectedRange[1]) {
                // 如果是选中行，添加css类
                if (this.selectedRows.includes(row)) {
                    clsname += ' is-selected'
                }
            }
            if (this.rowClassName) clsname += this.rowClassName(arguments[0]) || ''
            return clsname.trim()
        },
        // #region 表格样式
        customHeadCellStyle({ row, column, rowIndex, columnIndex }) {
            switch (this.tableStyle) {
                case 'concise':
                    return 'padding:0px;height:30px;'
                case 'normal':
                default:
                    return {
                        background: '#f0f0f0',
                        color: '#505050',
                        padding: 0,
                        height: '34px'
                    }
            }
        },
        customHeadRowStyle({ row, rowIndex }) {
            switch (this.tableStyle) {
                case 'concise':
                case 'normal':
                default:
                    return ''
            }
        },
        customRowStyle({ row, rowIndex }) {
            switch (this.tableStyle) {
                case 'concise':
                    return ''
                case 'normal':
                default:
                    return ''
            }
        },
        customCellStyle({ row, column, rowIndex, columnIndex }) {
            switch (this.tableStyle) {
                case 'concise':
                    return { padding: '2px 0 2px 0' }
                case 'normal':
                default:
                    return { padding: '3px 0 3px 0' }
            }
        },
        // #endregion 
    }
}
</script>

<style lang='scss'>
.uiot-table {
}
</style>